package javaer.starter.core.render;

import freemarker.template.TemplateException;
import javaer.starter.base.domain.dto.TemplateDTO;
import javaer.starter.core.IMatcher;
import javaer.starter.core.handler.ModuleContext;
import javaer.starter.util.FileUtil;
import javaer.starter.util.FreemarkerUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 模板渲染
 *
 * @author yangzhen
 * @date 2023/6/12 18:33
 * @since 1.0.0
 */
public interface ITemplateRender extends IMatcher, Serializable {

    /**
     * 注入临时变量
     *
     * @param params
     * @param args
     */
    default void inject(ModuleContext params, Object... args) {

    }

    /**
     * 渲染
     *
     * @param moduleContext
     * @param template
     * @param filePath
     * @throws TemplateException
     * @throws IOException
     */
    default void render(ModuleContext moduleContext, TemplateDTO template, Path filePath) throws TemplateException, IOException {
        FreemarkerUtil.writeFromDynamic(
                Paths.get(
                        moduleContext.getTypeName(),
                        moduleContext.getModuleName(),
                        template.getSourceDirectory(),
                        template.getRelativePath(),
                        template.getResolveName()
                ).toString(),
                filePath.toFile(),
                moduleContext);
    }

    /**
     * 渲染模板方法
     *
     * @param moduleContext
     * @param template
     * @throws TemplateException
     * @throws IOException
     */
    default void doRender(ModuleContext moduleContext, TemplateDTO template) throws TemplateException, IOException {
        try {
            Path filepath = getFilepath(moduleContext, template);
            inject(moduleContext, template);
            render(moduleContext, template, filepath);
        } finally {
            clear(moduleContext);
        }
    }

    /**
     * 获取文件路径
     *
     * @param moduleContext
     * @param template
     * @return
     * @throws IOException
     */
    default Path getFilepath(ModuleContext moduleContext, TemplateDTO template) throws IOException {
        Path fileParentPath = getFileParentPath(moduleContext, template);
        Path filepath = fileParentPath.resolve(template.getResolveName());
        if (!Files.exists(filepath)) {
            Files.createFile(filepath);
        }
        return filepath;
    }

    /**
     * 获取文件的上级路径
     *
     * @param moduleContext
     * @param template
     * @return
     */
    default Path getFileParentPath(ModuleContext moduleContext, TemplateDTO template) throws IOException {
        // 模块路径
        Path fileParentPath = moduleContext.getModulePath();
        if (StringUtils.isNotBlank(template.getSourceDirectory())) {
            fileParentPath = fileParentPath.resolve(template.getSourceDirectory());
        }
        if (needBasePackagePath()) {
            fileParentPath = fileParentPath.resolve(moduleContext.getBasePackagePath());
        }
        if (StringUtils.isNotBlank(template.getRelativePath())) {
            fileParentPath = fileParentPath.resolve(template.getRelativePath());
        }

        FileUtil.createDirsIfNotExists(fileParentPath);

        return fileParentPath;
    }

    /**
     * 是否需要模块的包路径
     *
     * @return
     */
    default boolean needBasePackagePath() {
        return false;
    }

    /**
     * 清除临时变量
     *
     * @param moduleContext
     */
    default void clear(ModuleContext moduleContext) {
        moduleContext.getTempValues().clear();
    }
}
